package JVM.第06篇_垃圾回收篇;

/**
 * finalize()方法详解，
 *      前言，finalize() 是object的protected方法，
 *      子类可以覆盖该方法以实现资源清理工作，GC在回收对象之前调用该方法。
 *
 * finalize的作用
 *      (1)finalize()与C++中的析构函数不是对应的。
 *         C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉)，但Java中的finalize的调用具有不确定性
 *      (2)不建议用finalize方法完成“非内存资源”的清理工作，但建议用于:
 *           ①清理本地对象(通过JNI创建的对象);
 *           ②作为确保某排内存资源(如Socket、文件等)释放的一个补充:
 *                   在finalize方法中显式调用其他资源释放方法。
 *
 * finalize的问题
 *      (1)一些与finalize相关的方法，由于一些致命的缺陷，已经被废弃了，
 *      如System.runFinalizersOnExit()方法、Runtime.runFinalizersOnExit()方法
 *      (2)System.gc()与System.runFinalization()方法增加了finalize方法执行的机会，但不可盲目依赖它
 *      (3)Java语言规范并不保证finalize方法会被及时地执行、而且根本不会保证它们会被执行
 *      (4)finalize方法可能会带来性能问题。因为JVM通常在单独的低优先级线程中完成finalize的执行
 *      (5)对象再生问题: finalize方法中， 可将待回收对象赋值给GC Roots可达的对象引用，
 *                  从而达到对象再生的目的
 *      (6)finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法，
 *         但并不影响GC finalize的行为)
 *
 * finalize的执行过程(生命周期)
 *      (1)首先，大致描述一下finalize流程:
 *           当对象变成(GC Roots)不可达时，GC会判断该对象是否覆盖了finalize方法，若未覆盖，则直接将其回收。
 *           否则，若对象未执行过finalize方法，将其放入F-Queue队列，由一低优先级线程执行该队列中对象的finalize方法。
 *           执行finalize方法完毕后， GC会 再次判断该对象是否可达，若不可达，则进行回收，否则，对象“复活”。
 *      (2)具体的finalize流程:
 *      对象可由两种状态，涉及到两类状态空间，
 *       一是终结状态空间F = {unfinalized, finalizable,finalized};
 *       二是可达状态空间R = {reachable, finalizer-reachable, unreachable}.
 *      各状态含义如下:
 *           ●unfinalized:新建对象会先进入此状态，GC并未准备执行其finalize方法， 因为该对象是可达的
 *           ●finalizable:表示GC可对该对象执行finalize方法， GC已检测到该对象不可达。
 *                   正如前面所述，GC通过F-Queue队 列和一专用线程完成finalize的执行
 *           ●finalized:表示GC已经对该对象执行过finalize方法
 *           ●reachable: 表示GC Roots引用可达
 *           ●finalizer-reachable(f-reachable): 表示不是reachable, 但可通过某个finalizable对象可达
 *
 */
public class F2_finalize方法 {
    public static F2_finalize方法 f;
    public static void main(String[] args) throws Throwable {
        //当一个对象首次考虑要被回收时，会调用其 finalize()
        //因为 finalize()此方法可以被重写
        //第二次，就直接删除，无需调用

        F2_finalize方法 f0_相关概念 = new F2_finalize方法();

        //第一次也  是空   是因为 f 被至空了,
        //虽然重写的finalize方法  但是赋值的是当前，也就是  f0_相关概念  不是f
        f = f0_相关概念;

        // 第一次不是空   这个是因为  this就是 f
//        f = new F0_相关概念();


        f = null;
        System.gc();
        Thread.sleep(2000);
        if(f == null){
            System.out.println("第一次是空");
        }else{
            System.out.println("第一次不是空");
        }
        f = null;
        System.gc();
        Thread.sleep(1000);
        if(f == null){
            System.out.println("第二次是空");
        }else{
            System.out.println("第二次不是空");
        }

    }
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        f = this;
    }

}
